package edu.unipd.p2t.db;

import java.io.FileOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.util.Log;
 
/***
 * Classe per la gestione del database SQLite
 * 
 * @author Tonon Michele
 *
 */
public class SQLiteDatabaseAdapter extends SQLiteOpenHelper{
	private static SQLiteDatabase sqliteDb;  
	private static SQLiteDatabaseAdapter instance;
	private static final int DATABASE_VERSION = 1;  
	// the default database path is : /data/data/pkgNameOfYourApplication/databases/
	private static String DB_PATH_PREFIX = "/data/data/";
	private static String DB_PATH_SUFFIX = "/databases/";
	private static final String TAG = "SQLiteDatabaseAdapter";  
	private Context context;
 
	/***
	 * Costruttore
	 * 
	 * @param context	: app context
	 * @param name		: database name
	 * @param factory	: cursor Factory
	 * @param version	: DB version
	 */
	private SQLiteDatabaseAdapter(Context context, String name, CursorFactory factory, int version) {  
		super(context, name, factory, version);  
		this.context = context;
		Log.i(TAG, "Crea o apre database : "+name);
	} 
 
	/***
	 * Metodo di inizializzazione
	 * 
	 * @param context		: application context
	 * @param databaseName	: database name
	 */
	private static void initialize(Context context,String databaseName) {  
		if(instance == null) {  
			/**
			 * Try to check if there is an Original copy of DB in asset Directory
			 */
			if (!checkDatabase(databaseName)){
				// if not exists, I try to copy from asset dir 
				try {
					copyDataBase(context,databaseName);
				} catch (IOException e) {
					Log.e(TAG,"Database "+databaseName+" does not exists and there is no Original Version in Asset dir");
				}
			}
 
			Log.i(TAG, "Try to create instance of database ("+databaseName+")");
			instance = new SQLiteDatabaseAdapter(context, databaseName, null, DATABASE_VERSION);
			sqliteDb = instance.getWritableDatabase();
			Log.i(TAG, "instance of database ("+databaseName+") created !");
		}  
	}
	
	
 
	/***
	 * Istanza singleton
	 * 
	 * @param context		: application context
	 * @param databaseName	: database name
	 * @return				: singleton instance
	 */
	public static final SQLiteDatabaseAdapter getInstance(Context context,String databaseName) {  
		initialize(context,databaseName);  
		return instance;  
	}  
	/***
	 * Restituisce il database
	 * @return	database instance
	 */
	public SQLiteDatabase getDatabase() {  
		return sqliteDb;  
	}
	
	/**
	 * Creazione e popoloamento iniziale del database se non esiste
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.d(TAG, "onCreate : Creazione database");
		
		db.execSQL("CREATE TABLE IF NOT EXISTS messages ("+
		        " date VARCHAR(19)," +
		        " author VARCHAR(30)," +
		        " message VARCHAR(140)," +
		        " hop INT(10)," +
		        " hash VARCHAR(32)," +
		        " PRIMARY KEY(author,message)"+
		          ");");
		
		
		
		 /**db.execSQL("INSERT INTO messages" 
        + " (date, author, message, hop, hash)" 
        + " VALUES ('WERTYUIDJFHGKCLVODOSPAOSIDCJFRTI', '2010-03-25 00:14:00', 'Primo Messaggio',10);"); 
	 
		 db.execSQL("INSERT INTO messages" 
                 + " (date, author, message, hop, hash)" 
                 + " VALUES ('WERTYUIDJFHGKCLVODOSPAOSIDCJFRTI', '2010-03-25 00:14:01', 'Secondo messaggio',10);"); 
**/
		 

	}
	
	
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		Log.d(TAG, "onUpgrade : Niente da fare");
		/** � necessario definire questo metodo per concretizzare la classe, anche se non fa niente **/
	} 
 
	/***
	 * Method for Copy the database from asset directory to application's data directory
	 * @param databaseName	: database name
	 * @throws IOException	: exception if file does not exists
	 */
	private void copyDataBase (String databaseName) throws IOException{
		copyDataBase(context,databaseName);
	}
 
	/***
	 * Static method for copy the database from asset directory to application's data directory
	 * @param aContext		: application context
	 * @param databaseName	: database name
	 * @throws IOException	: exception if file does not exists
	 */
	private static void copyDataBase(Context aContext,String databaseName) throws IOException{
 
    	//Open your local db as the input stream
    	InputStream myInput = aContext.getAssets().open(databaseName);
 
 
    	// Path to the just created empty db
    	String outFileName = getDatabasePath(databaseName);
 
    	Log.i(TAG,"Tentativo di copiare il database locale in: "+outFileName);
 
    	//Open the empty db as the output stream
    	OutputStream myOutput = new FileOutputStream(outFileName);
 
    	//transfer bytes from the inputfile to the outputfile
    	byte[] buffer = new byte[1024];
    	int length;
    	while ((length = myInput.read(buffer))>0){
    		myOutput.write(buffer, 0, length);
    	}
 
    	//Close the streams
    	myOutput.flush();
    	myOutput.close();
    	myInput.close();
 
    	Log.i(TAG,"Database ("+databaseName+") copiato");
	}
 

 
	/***
	 * Static Method to check if database exists in application's data directory
	 * @param aContext		: application context
	 * @param databaseName	: database name
	 * @return				: boolean (true if exists)
	 */
	public static boolean checkDatabase(String databaseName){
		SQLiteDatabase checkDB = null;
 
		try{
			String myPath = getDatabasePath(databaseName);
 
	    	Log.i(TAG,"Tentativo di connettersi a : "+myPath);
			checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
			Log.i(TAG,"Database "+databaseName+" non trovato");
			checkDB.close();
		}catch(SQLiteException e){
			Log.i(TAG,"Il database "+databaseName+" non esiste!");
 
		}
 
		return checkDB != null ? true : false;
	}
 
 
	/***
	 * Static Method that returns database path in the application's data directory
	 * @param aContext		: application context
	 * @param databaseName	: database name
	 * @return				: complete path
	 */
	private static String getDatabasePath(String databaseName){
		return DB_PATH_PREFIX + "edu.unipd.p2t" +DB_PATH_SUFFIX+ databaseName;
	}	
}
